package com.star.rpc.protocol;

import com.star.rpc.modal.RpcRequest;
import com.star.rpc.modal.RpcResponse;
import com.star.rpc.serializer.Serializer;
import com.star.rpc.spi.SerializerFactory;
import io.netty.buffer.ByteBuf;
import io.vertx.core.buffer.Buffer;

/**
 * packageName com.star.rpc.protocol
 *
 * @author zerostart
 * @className ProtocolMessageDecoder
 * @date 2024/12/1
 * @description 消息协议解码器
 */
public class ProtocolMessageDecoder {



    public static ProtocolMessage<?> decode(Buffer buffer) throws Exception {
        // 分别从位置上读出
        ProtocolMessage.Header header = new ProtocolMessage.Header();
        // 第一个字节： 魔数
        byte magic = buffer.getByte(0);
        // 校验魔数
        if (magic != ProtocolConstant.PROTOCOL_MAGIC) {
            throw new RuntimeException("协议魔数不匹配, 消息magic非法");
        }
        header.setMagic(magic);
        header.setVersion(buffer.getByte(1));
        header.setSerializer(buffer.getByte(2));
        header.setType(buffer.getByte(3));
        header.setStatus(buffer.getByte(4));
        header.setRequestId(buffer.getByte(5));
        header.setBodyLength(buffer.getInt(13));
        // 解决粘包问题，只读指定长度的数据
        byte[] bodyBytes = buffer.getBytes(17, 17 + header.getBodyLength());
        // 解析消息体
        ProtocolMessageSerializerEnum serializerEnum = ProtocolMessageSerializerEnum.getEnumByKey(header.getSerializer());
        if (serializerEnum == null) {
            throw new RuntimeException("不支持的序列化类型, 序列化消息的协议不存在");
        }

        Serializer serializer = SerializerFactory.getInstance(serializerEnum.getValue());
        ProtocolMessageTypeEnum messageTypeEnum = ProtocolMessageTypeEnum.getEnumByKey(header.getType());

        if (messageTypeEnum == null) {
            throw new RuntimeException("不支持的协议类型, 序列化消息类型不存在");
        }

        switch (messageTypeEnum) {
            case REQUEST:
                RpcRequest request = serializer.deserialize(bodyBytes, RpcRequest.class);
                return new ProtocolMessage<>(header, request);
            case RESPONSE:
                RpcResponse response = serializer.deserialize(bodyBytes, RpcResponse.class);
                return new ProtocolMessage<>(header, response);
            case HEART_BEAT:
            case OTHERS:
            default:
                throw new RuntimeException("不支持的协议类型, 序列化消息类型不存在");
        }
    }
}
